<!--
Copyright Yahoo Inc.
SPDX-License-Identifier: Apache-2.0
-->
<script setup>
import { computed } from 'vue';
const props = defineProps({
  content: { // content can be any type with a valid .toString() -- or null/undefined
    validator (prop) {
      if (prop == null ||
          typeof prop === 'string' ||
          typeof prop === 'number' ||
          typeof prop === 'boolean' ||
          typeof prop === 'object') return true;
      console.log(`WARNING - unsupported type ${typeof prop} in highlight-text`);
      return false;
    },
    required: true
  },
  // an array of spans (ordered by start, non-overlapping), ex. [{start: 0, end: 2}, {start: 3, end: 7}]
  highlights: {
    type: Array,
    default () {
      return null;
    }
  },
  // highlight color: 'yellow' (default, for table search) or 'pink' (for URL query param)
  highlightColor: {
    type: String,
    default: 'yellow',
    validator (value) {
      return ['yellow', 'pink'].includes(value);
    }
  }
});
const text = computed(() => props.content ? props.content.toString() : undefined);
const spans = computed(() => {
  if (props.highlights == null) {
    return [{ start: 0, end: text.value.length, highlighted: false }];
  }

  const spanList = [];
  const expandedHighlights = [{ start: -1, end: 0 }, ...props.highlights];
  const correctHighlightStart = (span) => {
    if (span.end > text.value.length) {
      return Math.min(span.start, text.value.length - 3);
    }
    return span.start;
  };

  for (const [i, highlightedSpan] of expandedHighlights.entries()) {
    if (i !== 0) {
      if (highlightedSpan.end > text.value.length) {
        // snaps highlight onto '...' if it surpasses the length of the string -- then stops highlighting
        spanList.push({ highlighted: true, start: correctHighlightStart(highlightedSpan), end: text.value.length });
        break;
      }

      spanList.push({ highlighted: true, ...highlightedSpan });
    }

    const nonHighlightedStart = highlightedSpan.end;
    const nonHighlightedEnd = (i === expandedHighlights.length - 1) ? text.value.length : correctHighlightStart(expandedHighlights[i + 1]);
    if (nonHighlightedStart !== nonHighlightedEnd) {
      spanList.push({ highlighted: false, start: nonHighlightedStart, end: nonHighlightedEnd });
    }
  }
  return spanList;
});
</script>

<template>
  <span>
    <template v-if="highlights != null">
      <span
        v-for="{start, end, highlighted} in spans"
        :class="{
          'highlight-yellow': highlighted && highlightColor === 'yellow',
          'highlight-pink': highlighted && highlightColor === 'pink'
        }"
        :key="`span-${start}-${end}`">{{ text.substring(start, end) }}</span>
    </template>
    <template v-else>{{ content }}</template>
  </span>
</template>

<style scoped>
.highlight-yellow {
  background-color: #ffff00;
  color: black;
}

.highlight-pink {
  background-color: #ff1493;
  color: white;
}
</style>
